✨(backend) add limit on distinct reactions per comment#1978
✨(backend) add limit on distinct reactions per comment#1978maboukerfa wants to merge 2 commits intosuitenumerique:mainfrom
Conversation
0399104 to
af0eeff
Compare
lunika
left a comment
There was a problem hiding this comment.
I only focus on the backend part.
If possible, can you split in 2 commits ? A first one for the backend and a second one for the frontend ?
Thank you so much for your contribution
af0eeff to
390085d
Compare
390085d to
0356763
Compare
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughAdds a new setting Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@CHANGELOG.md`:
- Around line 12-14: The CHANGELOG.md is missing a blank line before the "###
Changed" heading which triggers markdownlint MD022; insert a single blank line
immediately above the "### Changed" heading (the block containing "### Changed"
and the list item "- ✨(backend) add limit on distinct reactions per comment
`#1978`") so the heading is separated from the previous paragraph.
In `@src/backend/core/api/viewsets.py`:
- Around line 2781-2805: The POST path is vulnerable to TOCTOU: acquire a DB
transaction and lock the parent comment row with select_for_update before
re-checking reactions and creating the Reaction; specifically wrap the logic
around the existing comment variable in an atomic transaction (using Django's
transaction.atomic()) and re-fetch the comment with
Comment.objects.select_for_update().get(pk=comment.pk), then perform the
existence check (models.Reaction.objects.filter(comment=comment,
emoji=emoji).exists()), re-evaluate comment.reactions.count() against
settings.REACTIONS_MAX_PER_COMMENT, and only then call
models.Reaction.objects.get_or_create(...) so the count/enforce-check and create
are done under the same lock.
In `@src/backend/impress/settings.py`:
- Around line 185-189: The REACTIONS_MAX_PER_COMMENT setting currently allows
negative or zero values; add a startup validation immediately after the
REACTIONS_MAX_PER_COMMENT declaration in src/backend/impress/settings.py that
reads the resolved integer and raises a clear configuration error (e.g.,
ValueError or Django's ImproperlyConfigured) if the value is less than 1 so the
process fails fast on bad envs like REACTIONS_MAX_PER_COMMENT=-1; reference the
REACTIONS_MAX_PER_COMMENT symbol and include the environ_name in the error
message for clarity.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsx`:
- Around line 6-10: The constructor default for maxReactions in
DocsThreadStoreAuth is out of sync with the backend (10 vs backend 15); update
the constructor parameter default (private readonly maxReactions: number = 10)
to match the backend default 15 or remove the inline default so callers (e.g.,
useComments which passes config?.REACTIONS_MAX_PER_COMMENT) always control the
value; locate the DocsThreadStoreAuth constructor and change the default
accordingly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 113c97ad-f0ef-4f98-89da-f86045632297
📒 Files selected for processing (8)
CHANGELOG.mdsrc/backend/core/api/viewsets.pysrc/backend/core/factories.pysrc/backend/core/tests/documents/test_api_documents_comments.pysrc/backend/impress/settings.pysrc/frontend/apps/impress/src/core/config/api/useConfig.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts
| if request.method == "POST": | ||
| emoji = serializer.validated_data["emoji"] | ||
|
|
||
| if ( | ||
| not models.Reaction.objects.filter( | ||
| comment=comment, emoji=emoji | ||
| ).exists() | ||
| and comment.reactions.count() >= settings.REACTIONS_MAX_PER_COMMENT | ||
| ): | ||
| return drf.response.Response( | ||
| { | ||
| "emoji": [ | ||
| _( | ||
| "A comment can have a maximum of %(max)d distinct reactions." | ||
| ) | ||
| % {"max": settings.REACTIONS_MAX_PER_COMMENT} | ||
| ] | ||
| }, | ||
| status=status.HTTP_400_BAD_REQUEST, | ||
| ) | ||
|
|
||
| reaction, created = models.Reaction.objects.get_or_create( | ||
| comment=comment, | ||
| emoji=serializer.validated_data["emoji"], | ||
| emoji=emoji, | ||
| ) |
There was a problem hiding this comment.
Serialize the limit check with the create step.
This is still a TOCTOU race: two concurrent POSTs with different new emojis can both observe count() < REACTIONS_MAX_PER_COMMENT and both create, leaving the comment above the configured cap. Since the backend limit is the main point of this PR, the POST path needs a transaction + row lock on the parent comment before the existence/count/create sequence.
Suggested fix
if request.method == "POST":
emoji = serializer.validated_data["emoji"]
-
- if (
- not models.Reaction.objects.filter(
- comment=comment, emoji=emoji
- ).exists()
- and comment.reactions.count() >= settings.REACTIONS_MAX_PER_COMMENT
- ):
- return drf.response.Response(
- {
- "emoji": [
- _(
- "A comment can have a maximum of %(max)d distinct reactions."
- )
- % {"max": settings.REACTIONS_MAX_PER_COMMENT}
- ]
- },
- status=status.HTTP_400_BAD_REQUEST,
- )
-
- reaction, created = models.Reaction.objects.get_or_create(
- comment=comment,
- emoji=emoji,
- )
+ with transaction.atomic():
+ comment = models.Comment.objects.select_for_update().get(pk=comment.pk)
+ reactions = models.Reaction.objects.filter(comment=comment)
+
+ if (
+ not reactions.filter(emoji=emoji).exists()
+ and reactions.count() >= settings.REACTIONS_MAX_PER_COMMENT
+ ):
+ return drf.response.Response(
+ {
+ "emoji": [
+ _(
+ "A comment can have a maximum of %(max)d distinct reactions."
+ )
+ % {"max": settings.REACTIONS_MAX_PER_COMMENT}
+ ]
+ },
+ status=status.HTTP_400_BAD_REQUEST,
+ )
+
+ reaction, created = models.Reaction.objects.get_or_create(
+ comment=comment,
+ emoji=emoji,
+ )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/core/api/viewsets.py` around lines 2781 - 2805, The POST path is
vulnerable to TOCTOU: acquire a DB transaction and lock the parent comment row
with select_for_update before re-checking reactions and creating the Reaction;
specifically wrap the logic around the existing comment variable in an atomic
transaction (using Django's transaction.atomic()) and re-fetch the comment with
Comment.objects.select_for_update().get(pk=comment.pk), then perform the
existence check (models.Reaction.objects.filter(comment=comment,
emoji=emoji).exists()), re-evaluate comment.reactions.count() against
settings.REACTIONS_MAX_PER_COMMENT, and only then call
models.Reaction.objects.get_or_create(...) so the count/enforce-check and create
are done under the same lock.
There was a problem hiding this comment.
@lunika, this is prone to race condition, a user can create a MAX+1 emoji if he spams emojis, is it worth fixing or it's an overkill ?
There was a problem hiding this comment.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
There was a problem hiding this comment.
I think it's overkill and I'm not ok to add a lock on the table.
0356763 to
af1448b
Compare
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
src/backend/core/api/viewsets.py (1)
2783-2803:⚠️ Potential issue | 🔴 CriticalTOCTOU race between the existence/count check and
get_or_create.Two concurrent POSTs with different new emojis can both observe
count() < REACTIONS_MAX_PER_COMMENTand both succeed, pushing the comment above the configured cap. Since the whole point of this PR is backend enforcement, the check + create should be serialized viatransaction.atomic()+select_for_update()on the parent comment (as already proposed in an earlier review). This comment has already been raised on a prior commit.Additionally, once you're inside the atomic block, you can reuse the prefetched
comment.reactions.all()vialen(...)instead of a secondCOUNTquery.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/core/api/viewsets.py` around lines 2783 - 2803, Wrap the existence/count check and the get_or_create call in a single transaction and lock the parent comment row to prevent TOCTOU races: start a transaction.atomic() and re-fetch the Comment with select_for_update() (use the same Comment instance used by the view), then check the number of distinct reactions using the prefetched comment.reactions.all() (use len(...) instead of .count()) and perform Reaction.objects.get_or_create(...) inside that atomic block; update the code paths around the POST handling in the viewset so the existence check and creation are serialized on the locked comment to enforce settings.REACTIONS_MAX_PER_COMMENT.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/backend/core/tests/documents/test_api_documents_comments.py`:
- Around line 881-900: The test test_create_reaction_exceeds_maximum claims
"here we set it to 10" but never overrides settings.REACTIONS_MAX_PER_COMMENT;
update the test to explicitly set the limit using the provided settings fixture
(e.g. assign settings.REACTIONS_MAX_PER_COMMENT = 10 before creating reactions)
so the test adds exactly 10 distinct reactions and then verifies behavior, or
alternatively change the docstring to reflect that it uses the default setting;
modify the test logic in test_create_reaction_exceeds_maximum to reference the
overridden value consistently.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`:
- Line 29: The code currently uses config?.REACTIONS_MAX_PER_COMMENT ?? 0 which
sets max reactions to 0 while config is still loading and prevents adding new
distinct emoji; change the fallback to the backend default (15) or gate
rendering until config is defined: update the expression to
config?.REACTIONS_MAX_PER_COMMENT ?? 15 (or wrap the reactions UI in a check
like if (config === undefined) show loading) and ensure callers such as
canAddReaction(comment, maxPerComment) receive the non-zero default or a
not-ready state.
---
Duplicate comments:
In `@src/backend/core/api/viewsets.py`:
- Around line 2783-2803: Wrap the existence/count check and the get_or_create
call in a single transaction and lock the parent comment row to prevent TOCTOU
races: start a transaction.atomic() and re-fetch the Comment with
select_for_update() (use the same Comment instance used by the view), then check
the number of distinct reactions using the prefetched comment.reactions.all()
(use len(...) instead of .count()) and perform
Reaction.objects.get_or_create(...) inside that atomic block; update the code
paths around the POST handling in the viewset so the existence check and
creation are serialized on the locked comment to enforce
settings.REACTIONS_MAX_PER_COMMENT.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 9d3574e2-bf82-4ae5-a5c3-064e079f28e9
📒 Files selected for processing (5)
src/backend/core/api/viewsets.pysrc/backend/core/tests/documents/test_api_documents_comments.pysrc/frontend/apps/impress/src/core/config/api/useConfig.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts
| new DocsThreadStoreAuth( | ||
| encodeURIComponent(user?.full_name || ''), | ||
| canComment, | ||
| config?.REACTIONS_MAX_PER_COMMENT ?? 0, |
There was a problem hiding this comment.
Minor: ?? 0 disables all new reactions until config loads.
When config hasn't resolved yet (first load) or cached config predates this field, REACTIONS_MAX_PER_COMMENT is undefined and this falls back to 0, which gates canAddReaction(..., undefined) to false and blocks any new distinct emoji. This is briefly user-visible because useQuery seeds initialData from localStorage before the refetch completes.
Consider using the backend's documented default (15) as the fallback, or rendering the picker as loading until config is defined:
💡 Optional refactor
- config?.REACTIONS_MAX_PER_COMMENT ?? 0,
+ config?.REACTIONS_MAX_PER_COMMENT ?? 15,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| config?.REACTIONS_MAX_PER_COMMENT ?? 0, | |
| config?.REACTIONS_MAX_PER_COMMENT ?? 15, |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`
at line 29, The code currently uses config?.REACTIONS_MAX_PER_COMMENT ?? 0 which
sets max reactions to 0 while config is still loading and prevents adding new
distinct emoji; change the fallback to the backend default (15) or gate
rendering until config is defined: update the expression to
config?.REACTIONS_MAX_PER_COMMENT ?? 15 (or wrap the reactions UI in a check
like if (config === undefined) show loading) and ensure callers such as
canAddReaction(comment, maxPerComment) receive the non-zero default or a
not-ready state.
af1448b to
c0cf107
Compare
There was a problem hiding this comment.
♻️ Duplicate comments (3)
src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts (1)
31-31:⚠️ Potential issue | 🟡 MinorDon't fall back to
0before config loads.When
/configis still unresolved, ordocs_configwas cached before this field existed,0disables every new distinct emoji until the refetch completes. Use the backend default (15) or keep the picker disabled until config is ready.Suggested fix
- config?.REACTIONS_MAX_PER_COMMENT ?? 0, + config?.REACTIONS_MAX_PER_COMMENT ?? 15,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts` at line 31, The fallback to 0 for config?.REACTIONS_MAX_PER_COMMENT is disabling emoji usage before config loads; change the logic in useComments (the place using config?.REACTIONS_MAX_PER_COMMENT) to avoid returning 0 as the default: either fall back to the backend default of 15 (e.g., use config?.REACTIONS_MAX_PER_COMMENT ?? 15) or gate the picker until config is ready (return undefined/null or a disabled state while config is unresolved), ensuring REACTIONS_MAX_PER_COMMENT is not forced to 0 before the real config is available.src/backend/core/tests/documents/test_api_documents_comments.py (1)
881-901:⚠️ Potential issue | 🟡 MinorPin the reaction cap inside the test.
The docstring says this test sets the limit to
10, but it still inherits whateversettings.REACTIONS_MAX_PER_COMMENTis at runtime. Overriding it via the fixture keeps the test deterministic and shorter.Suggested fix
def test_create_reaction_exceeds_maximum(settings): """ Users should not be able to add more than REACTIONS_MAX_PER_COMMENT - (here we set it to 10) distinct emoji reactions to a comment. + distinct emoji reactions to a comment. They should, however, be able to add themselves to an existing reaction. """ + settings.REACTIONS_MAX_PER_COMMENT = 10 + user1 = factories.UserFactory() user2 = factories.UserFactory() @@ - max_reactions = settings.REACTIONS_MAX_PER_COMMENT + max_reactions = settings.REACTIONS_MAX_PER_COMMENT🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/core/tests/documents/test_api_documents_comments.py` around lines 881 - 901, The test test_create_reaction_exceeds_maximum relies on settings.REACTIONS_MAX_PER_COMMENT at runtime; pin this cap inside the test to make it deterministic by setting a local constant (e.g. MAX_REACTIONS = 10) and use that value when generating emojis and asserting behavior instead of reading settings.REACTIONS_MAX_PER_COMMENT, or explicitly override the Django setting for the test (e.g. with monkeypatch or override_settings) to set REACTIONS_MAX_PER_COMMENT = 10 before calling factories.ReactionFactory.generate_emojis and the rest of the test logic so the test always runs with the intended limit.src/backend/impress/settings.py (1)
193-197:⚠️ Potential issue | 🟡 MinorReject non-positive
REACTIONS_MAX_PER_COMMENTat startup.
0or negative values silently disable every new distinct reaction in both the API and the UI. Please fail fast with a clear configuration error instead of changing behavior at runtime.Suggested guard
def post_setup(cls): """Post setup configuration. This is the place where you can configure settings that require other settings to be loaded. """ super().post_setup() + + if cls.REACTIONS_MAX_PER_COMMENT < 1: + raise ValueError( + "REACTIONS_MAX_PER_COMMENT must be >= 1 " + "(env: REACTIONS_MAX_PER_COMMENT)." + ) # The SENTRY_DSN setting should be available to activate sentry for an environment if cls.SENTRY_DSN is not None:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/impress/settings.py` around lines 193 - 197, The REACTIONS_MAX_PER_COMMENT setting currently allows 0 or negative values which silently disable reactions; add a startup validation right after the REACTIONS_MAX_PER_COMMENT definition that checks its resolved integer is > 0 and raises an explicit configuration error if not (e.g. raise django.core.exceptions.ImproperlyConfigured or ValueError) with a clear message referencing REACTIONS_MAX_PER_COMMENT and the environment variable REACTIONS_MAX_PER_COMMENT (environ_name) so misconfiguration fails fast.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/backend/core/tests/documents/test_api_documents_comments.py`:
- Around line 881-901: The test test_create_reaction_exceeds_maximum relies on
settings.REACTIONS_MAX_PER_COMMENT at runtime; pin this cap inside the test to
make it deterministic by setting a local constant (e.g. MAX_REACTIONS = 10) and
use that value when generating emojis and asserting behavior instead of reading
settings.REACTIONS_MAX_PER_COMMENT, or explicitly override the Django setting
for the test (e.g. with monkeypatch or override_settings) to set
REACTIONS_MAX_PER_COMMENT = 10 before calling
factories.ReactionFactory.generate_emojis and the rest of the test logic so the
test always runs with the intended limit.
In `@src/backend/impress/settings.py`:
- Around line 193-197: The REACTIONS_MAX_PER_COMMENT setting currently allows 0
or negative values which silently disable reactions; add a startup validation
right after the REACTIONS_MAX_PER_COMMENT definition that checks its resolved
integer is > 0 and raises an explicit configuration error if not (e.g. raise
django.core.exceptions.ImproperlyConfigured or ValueError) with a clear message
referencing REACTIONS_MAX_PER_COMMENT and the environment variable
REACTIONS_MAX_PER_COMMENT (environ_name) so misconfiguration fails fast.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`:
- Line 31: The fallback to 0 for config?.REACTIONS_MAX_PER_COMMENT is disabling
emoji usage before config loads; change the logic in useComments (the place
using config?.REACTIONS_MAX_PER_COMMENT) to avoid returning 0 as the default:
either fall back to the backend default of 15 (e.g., use
config?.REACTIONS_MAX_PER_COMMENT ?? 15) or gate the picker until config is
ready (return undefined/null or a disabled state while config is unresolved),
ensuring REACTIONS_MAX_PER_COMMENT is not forced to 0 before the real config is
available.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 5514d8b4-455b-4654-8039-839a2be32ed4
📒 Files selected for processing (8)
CHANGELOG.mdsrc/backend/core/api/viewsets.pysrc/backend/core/factories.pysrc/backend/core/tests/documents/test_api_documents_comments.pysrc/backend/impress/settings.pysrc/frontend/apps/impress/src/core/config/api/useConfig.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts
c0cf107 to
d119fea
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
src/backend/impress/settings.py (1)
193-197:⚠️ Potential issue | 🟡 MinorFail fast on invalid reaction limits.
Line 193-Line 197 currently allows
REACTIONS_MAX_PER_COMMENT <= 0. A bad env value can silently disable new reactions. Validate at startup and raise a configuration error early.Suggested fix
class Base(Configuration): @@ def post_setup(cls): @@ super().post_setup() + if cls.REACTIONS_MAX_PER_COMMENT < 1: + raise ValueError( + "REACTIONS_MAX_PER_COMMENT must be >= 1 (env: REACTIONS_MAX_PER_COMMENT)." + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/impress/settings.py` around lines 193 - 197, REACTIONS_MAX_PER_COMMENT currently permits non-positive values from the environment which can silently disable reactions; add a startup validation in settings.py to check that REACTIONS_MAX_PER_COMMENT > 0 (after the IntegerValue is resolved) and raise a clear configuration error (e.g., ValueError or Django's ImproperlyConfigured) if the value is <= 0 so invalid env settings fail fast; update the settings initialization logic around the REACTIONS_MAX_PER_COMMENT symbol to perform this check and raise with a descriptive message.src/backend/core/tests/documents/test_api_documents_comments.py (1)
940-959:⚠️ Potential issue | 🟡 MinorAlign test setup with its documented behavior.
Line 942 says “here we set it to 10”, but the test never overrides the setting; it uses current runtime config instead.
Suggested fix
def test_create_reaction_exceeds_maximum(settings): @@ - user1 = factories.UserFactory() + settings.REACTIONS_MAX_PER_COMMENT = 10 + user1 = factories.UserFactory() @@ - max_reactions = settings.REACTIONS_MAX_PER_COMMENT + max_reactions = settings.REACTIONS_MAX_PER_COMMENT🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/core/tests/documents/test_api_documents_comments.py` around lines 940 - 959, The test claims "here we set it to 10" but reads settings.REACTIONS_MAX_PER_COMMENT at runtime; fix by explicitly setting the limit to 10 for the test (e.g., use Django's override_settings or monkeypatch to set settings.REACTIONS_MAX_PER_COMMENT = 10) before computing max_reactions and calling factories.ReactionFactory.generate_emojis; ensure the code that references max_reactions (the variable max_reactions and the call to factories.ReactionFactory.generate_emojis) uses this overridden value so the test matches its docstring.src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts (1)
31-31:⚠️ Potential issue | 🟠 MajorAvoid
0as fallback for max reactions.Line 31 (
config?.REACTIONS_MAX_PER_COMMENT ?? 0) temporarily disables adding new distinct reactions before config resolves (or when cached config predates this field).Suggested fix
- config?.REACTIONS_MAX_PER_COMMENT ?? 0, + config?.REACTIONS_MAX_PER_COMMENT ?? 15,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts` at line 31, The current fallback of 0 for config?.REACTIONS_MAX_PER_COMMENT prevents adding reactions until config loads; in useComments.ts replace the fallback (the expression using REACTIONS_MAX_PER_COMMENT) with a permissive default so reactions remain allowed (e.g., use config?.REACTIONS_MAX_PER_COMMENT ?? Number.POSITIVE_INFINITY or a sensible constant like DEFAULT_MAX_REACTIONS > 0) and ensure any UI checks treat Infinity/undefined as "no enforced limit". Update references to REACTIONS_MAX_PER_COMMENT in the useComments hook to use that new default value.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`:
- Line 8: The import ordering in useComments.ts violates the frontend lint rule;
reorder the imports so that external/library imports come first, then absolute
aliases (e.g., '@/core'), and then relative imports used in this file;
specifically adjust the import of useConfig so it appears in the correct group
relative to other imports in the module (locate the import statement "import {
useConfig } from '@/core';" in useComments.ts and move it to the appropriate
position to satisfy the lint-front ordering rules).
---
Duplicate comments:
In `@src/backend/core/tests/documents/test_api_documents_comments.py`:
- Around line 940-959: The test claims "here we set it to 10" but reads
settings.REACTIONS_MAX_PER_COMMENT at runtime; fix by explicitly setting the
limit to 10 for the test (e.g., use Django's override_settings or monkeypatch to
set settings.REACTIONS_MAX_PER_COMMENT = 10) before computing max_reactions and
calling factories.ReactionFactory.generate_emojis; ensure the code that
references max_reactions (the variable max_reactions and the call to
factories.ReactionFactory.generate_emojis) uses this overridden value so the
test matches its docstring.
In `@src/backend/impress/settings.py`:
- Around line 193-197: REACTIONS_MAX_PER_COMMENT currently permits non-positive
values from the environment which can silently disable reactions; add a startup
validation in settings.py to check that REACTIONS_MAX_PER_COMMENT > 0 (after the
IntegerValue is resolved) and raise a clear configuration error (e.g.,
ValueError or Django's ImproperlyConfigured) if the value is <= 0 so invalid env
settings fail fast; update the settings initialization logic around the
REACTIONS_MAX_PER_COMMENT symbol to perform this check and raise with a
descriptive message.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`:
- Line 31: The current fallback of 0 for config?.REACTIONS_MAX_PER_COMMENT
prevents adding reactions until config loads; in useComments.ts replace the
fallback (the expression using REACTIONS_MAX_PER_COMMENT) with a permissive
default so reactions remain allowed (e.g., use config?.REACTIONS_MAX_PER_COMMENT
?? Number.POSITIVE_INFINITY or a sensible constant like DEFAULT_MAX_REACTIONS >
0) and ensure any UI checks treat Infinity/undefined as "no enforced limit".
Update references to REACTIONS_MAX_PER_COMMENT in the useComments hook to use
that new default value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: eb3b8518-189b-4851-b16e-7be870565904
📒 Files selected for processing (8)
CHANGELOG.mdsrc/backend/core/api/viewsets.pysrc/backend/core/factories.pysrc/backend/core/tests/documents/test_api_documents_comments.pysrc/backend/impress/settings.pysrc/frontend/apps/impress/src/core/config/api/useConfig.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts
d119fea to
ede3d48
Compare
Implement a configurable limit (default: 15) on the number of distinct emoji reactions per comment. - Backend validation ensures the limit cannot be exceeded via API Signed-off-by: Mohamed El Amine BOUKERFA <boukerfa.ma@gmail.com>
Prevent users from adding more reactions once the per-message limit has been exceeded. It Disables reaction buttons when limit is reached Signed-off-by: Mohamed El Amine BOUKERFA <boukerfa.ma@gmail.com>
d73686b to
3be8fc8
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (4)
src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts (2)
8-8:⚠️ Potential issue | 🟡 MinorReorder imports to match the frontend lint rule.
Line 8 reintroduces the alias-ordering issue (
@/coreshould be grouped before@/cunningham).🧹 Suggested reorder
+import { useConfig } from '@/core'; import { useCunninghamTheme } from '@/cunningham'; import { User, avatarUrlFromName } from '@/features/auth'; import { useEditorStore } from '@/features/docs/doc-editor/stores'; import { Doc, useProviderStore } from '@/features/docs/doc-management'; -import { useConfig } from '@/core';🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts` at line 8, Reorder the import groups in useComments.ts so alias '@/core' appears before '@/cunningham' to satisfy the frontend alias-ordering lint rule; specifically move or reorder the line importing useConfig (import { useConfig } from '@/core') so it is grouped prior to any imports from '@/cunningham' (and ensure import grouping/ordering for other aliases follows the same rule).
31-31:⚠️ Potential issue | 🟡 MinorUse a non-zero fallback for
maxReactionswhile config is loading.Line 31 falls back to
0, which temporarily disables adding new distinct reactions before config resolves.💡 Suggested fix
- config?.REACTIONS_MAX_PER_COMMENT ?? 0, + config?.REACTIONS_MAX_PER_COMMENT ?? 15,🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts` at line 31, The fallback for config?.REACTIONS_MAX_PER_COMMENT currently uses 0 which blocks adding reactions while config loads; in useComments.ts change the fallback to a sensible non-zero default (e.g., DEFAULT_MAX_REACTIONS = 8) and use that instead of 0 for maxReactions (referencing config?.REACTIONS_MAX_PER_COMMENT and the maxReactions variable) so distinct reactions remain enabled until the real config resolves.src/backend/core/tests/documents/test_api_documents_comments.py (1)
940-943:⚠️ Potential issue | 🟡 MinorMake the test setup match the stated scenario (“set to 10”).
Lines 940-943 state a fixed limit of 10, but the test currently uses whatever default is configured at runtime.
✅ Suggested fix
def test_create_reaction_exceeds_maximum(settings): """ Users should not be able to add more than REACTIONS_MAX_PER_COMMENT (here we set it to 10) distinct emoji reactions to a comment. They should, however, be able to add themselves to an existing reaction. """ + settings.REACTIONS_MAX_PER_COMMENT = 10 user1 = factories.UserFactory() user2 = factories.UserFactory() @@ - max_reactions = settings.REACTIONS_MAX_PER_COMMENT + max_reactions = settings.REACTIONS_MAX_PER_COMMENTAlso applies to: 958-959
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/core/tests/documents/test_api_documents_comments.py` around lines 940 - 943, The test asserts a fixed limit of 10 reactions but currently uses the runtime default; explicitly set the limit to 10 in the test setup by patching the constant or configuration used by the code under test (e.g., monkeypatch core.constants.REACTIONS_MAX_PER_COMMENT = 10 or override the app setting the code reads) before creating reactions, and apply the same explicit override in the related assertions (the blocks around REACTIONS_MAX_PER_COMMENT usage at the other affected lines) so the test environment matches the stated scenario.src/backend/impress/settings.py (1)
193-197:⚠️ Potential issue | 🟠 MajorFail fast on invalid
REACTIONS_MAX_PER_COMMENTvalues.Lines 193-197 accept invalid values (e.g.,
0/negative), which silently changes API/UI behavior. Add a startup guard inpost_setupto enforce>= 1.🛡️ Suggested guard
def post_setup(cls): """Post setup configuration. This is the place where you can configure settings that require other settings to be loaded. """ super().post_setup() + + if cls.REACTIONS_MAX_PER_COMMENT < 1: + raise ValueError( + "REACTIONS_MAX_PER_COMMENT must be >= 1 (env: REACTIONS_MAX_PER_COMMENT)." + ) # The SENTRY_DSN setting should be available to activate sentry for an environment if cls.SENTRY_DSN is not None:🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/impress/settings.py` around lines 193 - 197, Add a startup guard in the settings module's post_setup to validate REACTIONS_MAX_PER_COMMENT: read the configured REACTIONS_MAX_PER_COMMENT value, and if it is less than 1 raise a clear startup exception (e.g., ValueError or ImproperlyConfigured) with a message explaining the invalid value and required minimum; reference the REACTIONS_MAX_PER_COMMENT symbol and implement this check inside the existing post_setup function so the app fails fast on 0/negative values.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/backend/core/factories.py`:
- Around line 239-242: The method generate_emojis currently uses the
module-level fake.unique registry which can leak state between tests; change it
to create and use a fresh Faker instance inside the generate_emojis classmethod
(e.g., instantiate Faker() locally and call its .unique.emoji() to produce n
emojis) so uniqueness is scoped to that instance and does not share global
state—replace uses of the module-level fake.unique in generate_emojis with a
local Faker().unique to isolate/avoid cross-test leakage.
---
Duplicate comments:
In `@src/backend/core/tests/documents/test_api_documents_comments.py`:
- Around line 940-943: The test asserts a fixed limit of 10 reactions but
currently uses the runtime default; explicitly set the limit to 10 in the test
setup by patching the constant or configuration used by the code under test
(e.g., monkeypatch core.constants.REACTIONS_MAX_PER_COMMENT = 10 or override the
app setting the code reads) before creating reactions, and apply the same
explicit override in the related assertions (the blocks around
REACTIONS_MAX_PER_COMMENT usage at the other affected lines) so the test
environment matches the stated scenario.
In `@src/backend/impress/settings.py`:
- Around line 193-197: Add a startup guard in the settings module's post_setup
to validate REACTIONS_MAX_PER_COMMENT: read the configured
REACTIONS_MAX_PER_COMMENT value, and if it is less than 1 raise a clear startup
exception (e.g., ValueError or ImproperlyConfigured) with a message explaining
the invalid value and required minimum; reference the REACTIONS_MAX_PER_COMMENT
symbol and implement this check inside the existing post_setup function so the
app fails fast on 0/negative values.
In
`@src/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts`:
- Line 8: Reorder the import groups in useComments.ts so alias '@/core' appears
before '@/cunningham' to satisfy the frontend alias-ordering lint rule;
specifically move or reorder the line importing useConfig (import { useConfig }
from '@/core') so it is grouped prior to any imports from '@/cunningham' (and
ensure import grouping/ordering for other aliases follows the same rule).
- Line 31: The fallback for config?.REACTIONS_MAX_PER_COMMENT currently uses 0
which blocks adding reactions while config loads; in useComments.ts change the
fallback to a sensible non-zero default (e.g., DEFAULT_MAX_REACTIONS = 8) and
use that instead of 0 for maxReactions (referencing
config?.REACTIONS_MAX_PER_COMMENT and the maxReactions variable) so distinct
reactions remain enabled until the real config resolves.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 69004058-0564-42e9-ad3e-5d33d46b5f21
📒 Files selected for processing (9)
CHANGELOG.mdsrc/backend/core/api/viewsets.pysrc/backend/core/factories.pysrc/backend/core/tests/documents/test_api_documents_comments.pysrc/backend/core/tests/test_api_config.pysrc/backend/impress/settings.pysrc/frontend/apps/impress/src/core/config/api/useConfig.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/DocsThreadStoreAuth.tsxsrc/frontend/apps/impress/src/features/docs/doc-editor/components/comments/useComments.ts
| @classmethod | ||
| def generate_emojis(cls, n=10): | ||
| """Generate a list of n unique emojis.""" | ||
| return [fake.unique.emoji() for _ in range(n)] |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Avoid shared fake.unique state across test cases.
Line 242 relies on a module-level unique registry, which can leak state between tests and make failures order-dependent.
♻️ Suggested refactor
`@classmethod`
def generate_emojis(cls, n=10):
"""Generate a list of n unique emojis."""
- return [fake.unique.emoji() for _ in range(n)]
+ faker = Faker()
+ return [faker.unique.emoji() for _ in range(n)]📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| @classmethod | |
| def generate_emojis(cls, n=10): | |
| """Generate a list of n unique emojis.""" | |
| return [fake.unique.emoji() for _ in range(n)] | |
| `@classmethod` | |
| def generate_emojis(cls, n=10): | |
| """Generate a list of n unique emojis.""" | |
| faker = Faker() | |
| return [faker.unique.emoji() for _ in range(n)] |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/core/factories.py` around lines 239 - 242, The method
generate_emojis currently uses the module-level fake.unique registry which can
leak state between tests; change it to create and use a fresh Faker instance
inside the generate_emojis classmethod (e.g., instantiate Faker() locally and
call its .unique.emoji() to produce n emojis) so uniqueness is scoped to that
instance and does not share global state—replace uses of the module-level
fake.unique in generate_emojis with a local Faker().unique to isolate/avoid
cross-test leakage.
Purpose
The current implementation allows users to add an unlimited number of reactions per comment.
Because the
/threadsendpoint is called on document load, having multiple comments withthousands of reactions each could significantly impact page load performance.
Proposal
Implement a configurable limit (default: 15) on the number of distinct emoji reactions per comment.
Screen.Recording.2026-03-11.at.00.21.53.mov